home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / ncurses / tinfo / captoinfo.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  20KB  |  837 lines

  1. /****************************************************************************
  2.  * Copyright (c) 1998-2001,2002 Free Software Foundation, Inc.              *
  3.  *                                                                          *
  4.  * Permission is hereby granted, free of charge, to any person obtaining a  *
  5.  * copy of this software and associated documentation files (the            *
  6.  * "Software"), to deal in the Software without restriction, including      *
  7.  * without limitation the rights to use, copy, modify, merge, publish,      *
  8.  * distribute, distribute with modifications, sublicense, and/or sell       *
  9.  * copies of the Software, and to permit persons to whom the Software is    *
  10.  * furnished to do so, subject to the following conditions:                 *
  11.  *                                                                          *
  12.  * The above copyright notice and this permission notice shall be included  *
  13.  * in all copies or substantial portions of the Software.                   *
  14.  *                                                                          *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS  *
  16.  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF               *
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.   *
  18.  * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,   *
  19.  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR    *
  20.  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR    *
  21.  * THE USE OR OTHER DEALINGS IN THE SOFTWARE.                               *
  22.  *                                                                          *
  23.  * Except as contained in this notice, the name(s) of the above copyright   *
  24.  * holders shall not be used in advertising or otherwise to promote the     *
  25.  * sale, use or other dealings in this Software without prior written       *
  26.  * authorization.                                                           *
  27.  ****************************************************************************/
  28.  
  29. /****************************************************************************
  30.  *  Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995               *
  31.  *     and: Eric S. Raymond <esr@snark.thyrsus.com>                         *
  32.  ****************************************************************************/
  33.  
  34. /*
  35.  *    captoinfo.c --- conversion between termcap and terminfo formats
  36.  *
  37.  *    The captoinfo() code was swiped from Ross Ridge's mytinfo package,
  38.  *    adapted to fit ncurses by Eric S. Raymond <esr@snark.thyrsus.com>.
  39.  *
  40.  *    There is just one entry point:
  41.  *
  42.  *    char *_nc_captoinfo(n, s, parametrized)
  43.  *
  44.  *    Convert value s for termcap string capability named n into terminfo
  45.  *    format.
  46.  *
  47.  *    This code recognizes all the standard 4.4BSD %-escapes:
  48.  *
  49.  *    %%       output `%'
  50.  *    %d       output value as in printf %d
  51.  *    %2       output value as in printf %2d
  52.  *    %3       output value as in printf %3d
  53.  *    %.       output value as in printf %c
  54.  *    %+x      add x to value, then do %.
  55.  *    %>xy     if value > x then add y, no output
  56.  *    %r       reverse order of two parameters, no output
  57.  *    %i       increment by one, no output
  58.  *    %n       exclusive-or all parameters with 0140 (Datamedia 2500)
  59.  *    %B       BCD (16*(value/10)) + (value%10), no output
  60.  *    %D       Reverse coding (value - 2*(value%16)), no output (Delta Data).
  61.  *
  62.  *    Also, %02 and %03 are accepted as synonyms for %2 and %3.
  63.  *
  64.  *    Besides all the standard termcap escapes, this translator understands
  65.  *    the following extended escapes:
  66.  *
  67.  *    used by GNU Emacs termcap libraries
  68.  *        %a[+*-/=][cp]x    GNU arithmetic.
  69.  *        %m        xor the first two parameters by 0177
  70.  *        %b        backup to previous parameter
  71.  *        %f        skip this parameter
  72.  *
  73.  *    used by the University of Waterloo (MFCF) termcap libraries
  74.  *        %-x     subtract parameter FROM char x and output it as a char
  75.  *        %ax     add the character x to parameter
  76.  *
  77.  *    If #define WATERLOO is on, also enable these translations:
  78.  *
  79.  *        %sx     subtract parameter FROM the character x
  80.  *
  81.  *    By default, this Waterloo translations are not compiled in, because
  82.  *    the Waterloo %s conflicts with the way terminfo uses %s in strings for
  83.  *    function programming.
  84.  *
  85.  *    Note the two definitions of %a: the GNU definition is translated if the
  86.  *    characters after the 'a' are valid for it, otherwise the UW definition
  87.  *    is translated.
  88.  */
  89.  
  90. #include <curses.priv.h>
  91.  
  92. #include <ctype.h>
  93. #include <tic.h>
  94.  
  95. MODULE_ID("$Id: captoinfo.c,v 1.43 2002/09/28 16:38:59 tom Exp $")
  96.  
  97. #define MAX_PUSHED    16    /* max # args we can push onto the stack */
  98.  
  99. static int stack[MAX_PUSHED];    /* the stack */
  100. static int stackptr;        /* the next empty place on the stack */
  101. static int onstack;        /* the top of stack */
  102. static int seenm;        /* seen a %m */
  103. static int seenn;        /* seen a %n */
  104. static int seenr;        /* seen a %r */
  105. static int param;        /* current parameter */
  106. static char *dp;        /* pointer to end of the converted string */
  107.  
  108. static char *my_string;
  109. static size_t my_length;
  110.  
  111. static char *
  112. init_string(void)
  113. /* initialize 'my_string', 'my_length' */
  114. {
  115.     if (my_string == 0)
  116.     my_string = typeMalloc(char, my_length = 256);
  117.     if (my_string == 0)
  118.     _nc_err_abort(MSG_NO_MEMORY);
  119.  
  120.     *my_string = '\0';
  121.     return my_string;
  122. }
  123.  
  124. static char *
  125. save_string(char *d, const char *const s)
  126. {
  127.     size_t have = (d - my_string);
  128.     size_t need = have + strlen(s) + 2;
  129.     if (need > my_length) {
  130.     my_string = (char *) realloc(my_string, my_length = (need + need));
  131.     if (my_string == 0)
  132.         _nc_err_abort(MSG_NO_MEMORY);
  133.     d = my_string + have;
  134.     }
  135.     (void) strcpy(d, s);
  136.     return d + strlen(d);
  137. }
  138.  
  139. static inline char *
  140. save_char(char *s, int c)
  141. {
  142.     static char temp[2];
  143.     temp[0] = (char) c;
  144.     return save_string(s, temp);
  145. }
  146.  
  147. static void
  148. push(void)
  149. /* push onstack on to the stack */
  150. {
  151.     if (stackptr > MAX_PUSHED)
  152.     _nc_warning("string too complex to convert");
  153.     else
  154.     stack[stackptr++] = onstack;
  155. }
  156.  
  157. static void
  158. pop(void)
  159. /* pop the top of the stack into onstack */
  160. {
  161.     if (stackptr == 0) {
  162.     if (onstack == 0)
  163.         _nc_warning("I'm confused");
  164.     else
  165.         onstack = 0;
  166.     } else
  167.     onstack = stack[--stackptr];
  168.     param++;
  169. }
  170.  
  171. static int
  172. cvtchar(register const char *sp)
  173. /* convert a character to a terminfo push */
  174. {
  175.     unsigned char c = 0;
  176.     int len;
  177.  
  178.     switch (*sp) {
  179.     case '\\':
  180.     switch (*++sp) {
  181.     case '\'':
  182.     case '$':
  183.     case '\\':
  184.     case '%':
  185.         c = *sp;
  186.         len = 2;
  187.         break;
  188.     case '\0':
  189.         c = '\\';
  190.         len = 1;
  191.         break;
  192.     case '0':
  193.     case '1':
  194.     case '2':
  195.     case '3':
  196.         len = 1;
  197.         while (isdigit(UChar(*sp))) {
  198.         c = 8 * c + (*sp++ - '0');
  199.         len++;
  200.         }
  201.         break;
  202.     default:
  203.         c = *sp;
  204.         len = 2;
  205.         break;
  206.     }
  207.     break;
  208.     case '^':
  209.     c = (*++sp & 0x1f);
  210.     len = 2;
  211.     break;
  212.     default:
  213.     c = *sp;
  214.     len = 1;
  215.     }
  216.     if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') {
  217.     dp = save_string(dp, "%\'");
  218.     dp = save_char(dp, c);
  219.     dp = save_char(dp, '\'');
  220.     } else {
  221.     dp = save_string(dp, "%{");
  222.     if (c > 99)
  223.         dp = save_char(dp, c / 100 + '0');
  224.     if (c > 9)
  225.         dp = save_char(dp, ((int) (c / 10)) % 10 + '0');
  226.     dp = save_char(dp, c % 10 + '0');
  227.     dp = save_char(dp, '}');
  228.     }
  229.     return len;
  230. }
  231.  
  232. static void
  233. getparm(int parm, int n)
  234. /* push n copies of param on the terminfo stack if not already there */
  235. {
  236.     if (seenr) {
  237.     if (parm == 1)
  238.         parm = 2;
  239.     else if (parm == 2)
  240.         parm = 1;
  241.     }
  242.     if (onstack == parm) {
  243.     if (n > 1) {
  244.         _nc_warning("string may not be optimal");
  245.         dp = save_string(dp, "%Pa");
  246.         while (n--) {
  247.         dp = save_string(dp, "%ga");
  248.         }
  249.     }
  250.     return;
  251.     }
  252.     if (onstack != 0)
  253.     push();
  254.  
  255.     onstack = parm;
  256.  
  257.     while (n--) {
  258.     dp = save_string(dp, "%p");
  259.     dp = save_char(dp, '0' + parm);
  260.     }
  261.  
  262.     if (seenn && parm < 3) {
  263.     dp = save_string(dp, "%{96}%^");
  264.     }
  265.  
  266.     if (seenm && parm < 3) {
  267.     dp = save_string(dp, "%{127}%^");
  268.     }
  269. }
  270.  
  271. /*
  272.  * Convert a termcap string to terminfo format.
  273.  * 'cap' is the relevant terminfo capability index.
  274.  * 's' is the string value of the capability.
  275.  * 'parametrized' tells what type of translations to do:
  276.  *    % translations if 1
  277.  *    pad translations if >=0
  278.  */
  279. char *
  280. _nc_captoinfo(const char *cap, const char *s, int const parametrized)
  281. {
  282.     const char *capstart;
  283.  
  284.     stackptr = 0;
  285.     onstack = 0;
  286.     seenm = 0;
  287.     seenn = 0;
  288.     seenr = 0;
  289.     param = 1;
  290.  
  291.     dp = init_string();
  292.  
  293.     /* skip the initial padding (if we haven't been told not to) */
  294.     capstart = 0;
  295.     if (s == 0)
  296.     s = "";
  297.     if (parametrized >= 0 && isdigit(UChar(*s)))
  298.     for (capstart = s;; s++)
  299.         if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.'))
  300.         break;
  301.  
  302.     while (*s != '\0') {
  303.     switch (*s) {
  304.     case '%':
  305.         s++;
  306.         if (parametrized < 1) {
  307.         dp = save_char(dp, '%');
  308.         break;
  309.         }
  310.         switch (*s++) {
  311.         case '%':
  312.         dp = save_char(dp, '%');
  313.         break;
  314.         case 'r':
  315.         if (seenr++ == 1) {
  316.             _nc_warning("saw %%r twice in %s", cap);
  317.         }
  318.         break;
  319.         case 'm':
  320.         if (seenm++ == 1) {
  321.             _nc_warning("saw %%m twice in %s", cap);
  322.         }
  323.         break;
  324.         case 'n':
  325.         if (seenn++ == 1) {
  326.             _nc_warning("saw %%n twice in %s", cap);
  327.         }
  328.         break;
  329.         case 'i':
  330.         dp = save_string(dp, "%i");
  331.         break;
  332.         case '6':
  333.         case 'B':
  334.         getparm(param, 1);
  335.         dp = save_string(dp, "%{10}%/%{16}%*");
  336.         getparm(param, 1);
  337.         dp = save_string(dp, "%{10}%m%+");
  338.         break;
  339.         case '8':
  340.         case 'D':
  341.         getparm(param, 2);
  342.         dp = save_string(dp, "%{2}%*%-");
  343.         break;
  344.         case '>':
  345.         getparm(param, 2);
  346.         /* %?%{x}%>%t%{y}%+%; */
  347.         dp = save_string(dp, "%?");
  348.         s += cvtchar(s);
  349.         dp = save_string(dp, "%>%t");
  350.         s += cvtchar(s);
  351.         dp = save_string(dp, "%+%;");
  352.         break;
  353.         case 'a':
  354.         if ((*s == '=' || *s == '+' || *s == '-'
  355.              || *s == '*' || *s == '/')
  356.             && (s[1] == 'p' || s[1] == 'c')
  357.             && s[2] != '\0') {
  358.             int l;
  359.             l = 2;
  360.             if (*s != '=')
  361.             getparm(param, 1);
  362.             if (s[1] == 'p') {
  363.             getparm(param + s[2] - '@', 1);
  364.             if (param != onstack) {
  365.                 pop();
  366.                 param--;
  367.             }
  368.             l++;
  369.             } else
  370.             l += cvtchar(s + 2);
  371.             switch (*s) {
  372.             case '+':
  373.             dp = save_string(dp, "%+");
  374.             break;
  375.             case '-':
  376.             dp = save_string(dp, "%-");
  377.             break;
  378.             case '*':
  379.             dp = save_string(dp, "%*");
  380.             break;
  381.             case '/':
  382.             dp = save_string(dp, "%/");
  383.             break;
  384.             case '=':
  385.             if (seenr) {
  386.                 if (param == 1)
  387.                 onstack = 2;
  388.                 else if (param == 2)
  389.                 onstack = 1;
  390.                 else
  391.                 onstack = param;
  392.             } else
  393.                 onstack = param;
  394.             break;
  395.             }
  396.             s += l;
  397.             break;
  398.         }
  399.         getparm(param, 1);
  400.         s += cvtchar(s);
  401.         dp = save_string(dp, "%+");
  402.         break;
  403.         case '+':
  404.         getparm(param, 1);
  405.         s += cvtchar(s);
  406.         dp = save_string(dp, "%+%c");
  407.         pop();
  408.         break;
  409.         case 's':
  410. #ifdef WATERLOO
  411.         s += cvtchar(s);
  412.         getparm(param, 1);
  413.         dp = save_string(dp, "%-");
  414. #else
  415.         getparm(param, 1);
  416.         dp = save_string(dp, "%s");
  417.         pop();
  418. #endif /* WATERLOO */
  419.         break;
  420.         case '-':
  421.         s += cvtchar(s);
  422.         getparm(param, 1);
  423.         dp = save_string(dp, "%-%c");
  424.         pop();
  425.         break;
  426.         case '.':
  427.         getparm(param, 1);
  428.         dp = save_string(dp, "%c");
  429.         pop();
  430.         break;
  431.         case '0':        /* not clear any of the historical termcaps did this */
  432.         if (*s == '3')
  433.             goto see03;
  434.         else if (*s != '2')
  435.             goto invalid;
  436.         /* FALLTHRU */
  437.         case '2':
  438.         getparm(param, 1);
  439.         dp = save_string(dp, "%2d");
  440.         pop();
  441.         break;
  442.         case '3':
  443.           see03:
  444.         getparm(param, 1);
  445.         dp = save_string(dp, "%3d");
  446.         pop();
  447.         break;
  448.         case 'd':
  449.         getparm(param, 1);
  450.         dp = save_string(dp, "%d");
  451.         pop();
  452.         break;
  453.         case 'f':
  454.         param++;
  455.         break;
  456.         case 'b':
  457.         param--;
  458.         break;
  459.         case '\\':
  460.         dp = save_string(dp, "%\\");
  461.         break;
  462.         default:
  463.           invalid:
  464.         dp = save_char(dp, '%');
  465.         s--;
  466.         _nc_warning("unknown %% code %s (%#x) in %s",
  467.                 unctrl((chtype) *s), UChar(*s), cap);
  468.         break;
  469.         }
  470.         break;
  471. #ifdef REVISIBILIZE
  472.     case '\\':
  473.         dp = save_char(dp, *s++);
  474.         dp = save_char(dp, *s++);
  475.         break;
  476.     case '\n':
  477.         dp = save_string(dp, "\\n");
  478.         s++;
  479.         break;
  480.     case '\t':
  481.         dp = save_string(dp, "\\t");
  482.         s++;
  483.         break;
  484.     case '\r':
  485.         dp = save_string(dp, "\\r");
  486.         s++;
  487.         break;
  488.     case '\200':
  489.         dp = save_string(dp, "\\0");
  490.         s++;
  491.         break;
  492.     case '\f':
  493.         dp = save_string(dp, "\\f");
  494.         s++;
  495.         break;
  496.     case '\b':
  497.         dp = save_string(dp, "\\b");
  498.         s++;
  499.         break;
  500.     case ' ':
  501.         dp = save_string(dp, "\\s");
  502.         s++;
  503.         break;
  504.     case '^':
  505.         dp = save_string(dp, "\\^");
  506.         s++;
  507.         break;
  508.     case ':':
  509.         dp = save_string(dp, "\\:");
  510.         s++;
  511.         break;
  512.     case ',':
  513.         dp = save_string(dp, "\\,");
  514.         s++;
  515.         break;
  516.     default:
  517.         if (*s == '\033') {
  518.         dp = save_string(dp, "\\E");
  519.         s++;
  520.         } else if (*s > 0 && *s < 32) {
  521.         dp = save_char(dp, '^');
  522.         dp = save_char(dp, *s + '@');
  523.         s++;
  524.         } else if (*s <= 0 || *s >= 127) {
  525.         dp = save_char(dp, '\\');
  526.         dp = save_char(dp, ((*s & 0300) >> 6) + '0');
  527.         dp = save_char(dp, ((*s & 0070) >> 3) + '0');
  528.         dp = save_char(dp, (*s & 0007) + '0');
  529.         s++;
  530.         } else
  531.         dp = save_char(dp, *s++);
  532.         break;
  533. #else
  534.     default:
  535.         dp = save_char(dp, *s++);
  536.         break;
  537. #endif
  538.     }
  539.     }
  540.  
  541.     /*
  542.      * Now, if we stripped off some leading padding, add it at the end
  543.      * of the string as mandatory padding.
  544.      */
  545.     if (capstart) {
  546.     dp = save_string(dp, "$<");
  547.     for (s = capstart;; s++)
  548.         if (isdigit(UChar(*s)) || *s == '*' || *s == '.')
  549.         dp = save_char(dp, *s);
  550.         else
  551.         break;
  552.     dp = save_string(dp, "/>");
  553.     }
  554.  
  555.     (void) save_char(dp, '\0');
  556.     return (my_string);
  557. }
  558.  
  559. /*
  560.  * Check for an expression that corresponds to "%B" (BCD):
  561.  *    (parameter / 10) * 16 + (parameter % 10)
  562.  */
  563. static int
  564. bcd_expression(const char *str)
  565. {
  566.     /* leave this non-const for HPUX */
  567.     static char fmt[] = "%%p%c%%{10}%%/%%{16}%%*%%p%c%%{10}%%m%%+";
  568.     int len = 0;
  569.     char ch1, ch2;
  570.  
  571.     if (sscanf(str, fmt, &ch1, &ch2) == 2
  572.     && isdigit(UChar(ch1))
  573.     && isdigit(UChar(ch2))
  574.     && (ch1 == ch2)) {
  575.     len = 28;
  576. #ifndef NDEBUG
  577.     {
  578.         char buffer[80];
  579.         int tst;
  580.         sprintf(buffer, fmt, ch1, ch2);
  581.         tst = strlen(buffer) - 1;
  582.         assert(len == tst);
  583.     }
  584. #endif
  585.     }
  586.     return len;
  587. }
  588.  
  589. static char *
  590. save_tc_char(char *bufptr, int c1)
  591. {
  592.     char temp[80];
  593.  
  594.     if (is7bits(c1) && isprint(c1)) {
  595.     if (c1 == ':' || c1 == '\\')
  596.         bufptr = save_char(bufptr, '\\');
  597.     bufptr = save_char(bufptr, c1);
  598.     } else {
  599.     if (c1 == (c1 & 0x1f))    /* iscntrl() returns T on 255 */
  600.         (void) strcpy(temp, unctrl((chtype) c1));
  601.     else
  602.         (void) sprintf(temp, "\\%03o", c1);
  603.     bufptr = save_string(bufptr, temp);
  604.     }
  605.     return bufptr;
  606. }
  607.  
  608. static char *
  609. save_tc_inequality(char *bufptr, int c1, int c2)
  610. {
  611.     bufptr = save_string(bufptr, "%>");
  612.     bufptr = save_tc_char(bufptr, c1);
  613.     bufptr = save_tc_char(bufptr, c2);
  614.     return bufptr;
  615. }
  616.  
  617. /*
  618.  * Here are the capabilities infotocap assumes it can translate to:
  619.  *
  620.  *     %%       output `%'
  621.  *     %d       output value as in printf %d
  622.  *     %2       output value as in printf %2d
  623.  *     %3       output value as in printf %3d
  624.  *     %.       output value as in printf %c
  625.  *     %+c      add character c to value, then do %.
  626.  *     %>xy     if value > x then add y, no output
  627.  *     %r       reverse order of two parameters, no output
  628.  *     %i       increment by one, no output
  629.  *     %n       exclusive-or all parameters with 0140 (Datamedia 2500)
  630.  *     %B       BCD (16*(value/10)) + (value%10), no output
  631.  *     %D       Reverse coding (value - 2*(value%16)), no output (Delta Data).
  632.  *     %m       exclusive-or all parameters with 0177 (not in 4.4BSD)
  633.  */
  634.  
  635. /*
  636.  * Convert a terminfo string to termcap format.  Parameters are as in
  637.  * _nc_captoinfo().
  638.  */
  639. char *
  640. _nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parametrized)
  641. {
  642.     int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0;
  643.     const char *padding;
  644.     const char *trimmed = 0;
  645.     char ch1 = 0, ch2 = 0;
  646.     char *bufptr = init_string();
  647.     int len;
  648.     bool syntax_error = FALSE;
  649.  
  650.     /* we may have to move some trailing mandatory padding up front */
  651.     padding = str + strlen(str) - 1;
  652.     if (*padding == '>' && *--padding == '/') {
  653.     --padding;
  654.     while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
  655.         padding--;
  656.     if (*padding == '<' && *--padding == '$')
  657.         trimmed = padding;
  658.     padding += 2;
  659.  
  660.     while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*')
  661.         bufptr = save_char(bufptr, *padding++);
  662.     }
  663.  
  664.     for (; *str && str != trimmed; str++) {
  665.     int c1, c2;
  666.     char *cp = 0;
  667.  
  668.     if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) {
  669.         bufptr = save_char(bufptr, *++str);
  670.     } else if (str[0] == '$' && str[1] == '<') {    /* discard padding */
  671.         str += 2;
  672.         while (isdigit(UChar(*str))
  673.            || *str == '.'
  674.            || *str == '*'
  675.            || *str == '/'
  676.            || *str == '>')
  677.         str++;
  678.         --str;
  679.     } else if (str[0] == '%' && str[1] == '%') {    /* escaped '%' */
  680.         bufptr = save_string(bufptr, "%%");
  681.     } else if (*str != '%' || (parametrized < 1)) {
  682.         bufptr = save_char(bufptr, *str);
  683.     } else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) {
  684.         str = strchr(str, ';');
  685.         bufptr = save_tc_inequality(bufptr, c1, c2);
  686.     } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) {
  687.         str = strchr(str, ';');
  688.         bufptr = save_tc_inequality(bufptr, c1, c2);
  689.     } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) {
  690.         str = strchr(str, ';');
  691.         bufptr = save_tc_inequality(bufptr, c1, c2);
  692.     } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) {
  693.         str = strchr(str, ';');
  694.         bufptr = save_tc_inequality(bufptr, c1, c2);
  695.     } else if ((len = bcd_expression(str)) != 0) {
  696.         str += len;
  697.         bufptr = save_string(bufptr, "%B");
  698.     } else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1
  699.             || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1)
  700.            && (cp = strchr(str, '+'))) {
  701.         str = cp + 2;
  702.         bufptr = save_string(bufptr, "%+");
  703.  
  704.         if (ch1)
  705.         c1 = ch1;
  706.         bufptr = save_tc_char(bufptr, c1);
  707.     }
  708.     /* FIXME: this "works" for 'delta' */
  709.     else if (strncmp(str, "%{2}%*%-", 8) == 0) {
  710.         str += 7;
  711.         bufptr = save_string(bufptr, "%D");
  712.     } else if (strncmp(str, "%{96}%^", 7) == 0) {
  713.         str += 6;
  714.         if (saw_m++ == 0) {
  715.         bufptr = save_string(bufptr, "%n");
  716.         }
  717.     } else if (strncmp(str, "%{127}%^", 8) == 0) {
  718.         str += 7;
  719.         if (saw_n++ == 0) {
  720.         bufptr = save_string(bufptr, "%m");
  721.         }
  722.     } else {        /* cm-style format element */
  723.         str++;
  724.         switch (*str) {
  725.         case '%':
  726.         bufptr = save_char(bufptr, '%');
  727.         break;
  728.  
  729.         case '0':
  730.         case '1':
  731.         case '2':
  732.         case '3':
  733.         case '4':
  734.         case '5':
  735.         case '6':
  736.         case '7':
  737.         case '8':
  738.         case '9':
  739.         bufptr = save_char(bufptr, '%');
  740.         while (isdigit(UChar(*str)))
  741.             bufptr = save_char(bufptr, *str++);
  742.         if (strchr("doxX.", *str)) {
  743.             if (*str != 'd')    /* termcap doesn't have octal, hex */
  744.             return 0;
  745.         }
  746.         break;
  747.  
  748.         case 'd':
  749.         bufptr = save_string(bufptr, "%d");
  750.         break;
  751.  
  752.         case 'c':
  753.         bufptr = save_string(bufptr, "%.");
  754.         break;
  755.  
  756.         /*
  757.          * %s isn't in termcap, but it's convenient to pass it through
  758.          * so we can represent things like terminfo pfkey strings in
  759.          * termcap notation.
  760.          */
  761.         case 's':
  762.         bufptr = save_string(bufptr, "%s");
  763.         break;
  764.  
  765.         case 'p':
  766.         str++;
  767.         if (*str == '1')
  768.             seenone = 1;
  769.         else if (*str == '2') {
  770.             if (!seenone && !seentwo) {
  771.             bufptr = save_string(bufptr, "%r");
  772.             seentwo++;
  773.             }
  774.         } else if (*str >= '3')
  775.             return (0);
  776.         break;
  777.  
  778.         case 'i':
  779.         bufptr = save_string(bufptr, "%i");
  780.         break;
  781.  
  782.         default:
  783.         bufptr = save_char(bufptr, *str);
  784.         syntax_error = TRUE;
  785.         break;
  786.         }            /* endswitch (*str) */
  787.     }            /* endelse (*str == '%') */
  788.  
  789.     if (*str == '\0')
  790.         break;
  791.  
  792.     }                /* endwhile (*str) */
  793.  
  794.     return (syntax_error ? NULL : my_string);
  795. }
  796.  
  797. #ifdef MAIN
  798.  
  799. int curr_line;
  800.  
  801. int
  802. main(int argc, char *argv[])
  803. {
  804.     int c, tc = FALSE;
  805.  
  806.     while ((c = getopt(argc, argv, "c")) != EOF)
  807.     switch (c) {
  808.     case 'c':
  809.         tc = TRUE;
  810.         break;
  811.     }
  812.  
  813.     curr_line = 0;
  814.     for (;;) {
  815.     char buf[BUFSIZ];
  816.  
  817.     ++curr_line;
  818.     if (fgets(buf, sizeof(buf), stdin) == 0)
  819.         break;
  820.     buf[strlen(buf) - 1] = '\0';
  821.     _nc_set_source(buf);
  822.  
  823.     if (tc) {
  824.         char *cp = _nc_infotocap("to termcap", buf, 1);
  825.  
  826.         if (cp)
  827.         (void) fputs(cp, stdout);
  828.     } else
  829.         (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout);
  830.     (void) putchar('\n');
  831.     }
  832.     return (0);
  833. }
  834. #endif /* MAIN */
  835.  
  836. /* captoinfo.c ends here */
  837.